package REDES;



//Set up a Server that will receive a connection
//from a client, send a string to the client,
//and close the connection.

//Java core packages
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
//Java extension packages
import javax.swing.*;

import REDES.Connect.RunList;
public class Server4 extends JFrame {
	private static JTextField enterField;
	private static JTextArea displayArea;
	private static ServerSocket server;	
	protected static int counter = 0; protected static final int max = 10;
	protected static Multi[] m = new Multi[max]; 
	// set up GUI
	public Server4()
	{
		super( "Server" );

		Container container = getContentPane();

		// create enterField and register listener
		enterField = new JTextField();
		enterField.setEnabled( false );
		container.add( enterField, BorderLayout.NORTH );

		// create displayArea
		displayArea = new JTextArea();
		container.add( new JScrollPane( displayArea ),
				BorderLayout.CENTER );
		setSize( 400, 250 );setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible( true );
	}
	// execute application
	public static void main( String args[] ) throws IOException
	{
	new Server4();
	server = new ServerSocket( 5000, 100 );
	createListServer();
	connectListServer();
		while(true) {
			for (int i = 0; i < 10; i++) {
				if (m[i]==null) {
					new Thread(m[i] = new Multi( m,server.accept(), displayArea, enterField)).start(); 
					counter++;	System.out.println(counter);
					break;
				}
			}	updateList();
		}
	}
	private static void createListServer() {
		new Thread(new RunList()).start(); 
	}
	/**
	 * Metodo que conecta ao servidor responsavel pela lista de clientes;
	 */ 
	protected static ObjectOutputStream output2 = null;
	private static void connectListServer(){
		 Socket listClient;
		 ObjectInputStream is2 = null;
		try {
			listClient = new Socket("localhost",3000);
			System.out.println("conectado 3000");
			output2 = new ObjectOutputStream(
					listClient.getOutputStream() );
			is2 = new ObjectInputStream(listClient.getInputStream());
		} catch (UnknownHostException e) {
		System.out.println("error connecting to ListServer");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/** envia a lista de clientes conectados nesse servidor para o ListServer */
	private static void updateList(){
		try {
		for (int i = 0; i < m.length && m[i]!=null; i++) {
				output2.writeObject(m[i].connection.getRemoteSocketAddress().toString()+"//");
				//output2.writeObject("//"+m[i].connection.getInetAddress().getHostName()+"##"); 
				System.out.println("88:"+m[i].connection.getRemoteSocketAddress().toString());output2.flush();
			}
			
		} catch (IOException e) {
			System.out.println("erro ao enviar lista");
		} 
	}
	static class Multi extends Thread implements ActionListener{
		protected Multi[] m;
		protected 	Socket connection;
		protected  JTextArea displayArea;
		protected  JTextField enterField;
		protected  ObjectOutputStream output = null;
		protected  ObjectInputStream input = null;
		protected String message =""; Socket[] s;
		public Multi(Multi[] m,Socket client, JTextArea a, JTextField t){
			this.m = m;
			this.connection = client;
			this.displayArea = a;
			this.enterField = t;
			if (Server4.counter <1)
			this.enterField.addActionListener(this);
		}
		public void run(){
			this.runServer();
		}


		// set up and run server
		public void runServer()
		{
			// set up server to receive connections;
			// process connections
			try {
				// Step 1: Create a ServerSocket.			
				this.getStreams();
				// Step 3: Get input and output streams.
				// Step 4: Process connection.
				this.processConnection();
			
				// Step 5: Close connection.
				//closeConnection();

			}

			// process EOFException when client closes connection
			catch ( EOFException eofException ) {
				System.out.println( "Client terminated connection" );
			}

			// process problems with I/O
			catch ( IOException ioException ) {
				ioException.printStackTrace();
			}
		}

		// wait for connection to arrive, then display connection info


		// get streams to send and receive data
		protected void getStreams() throws IOException
		{
			// set up output stream for objects
			output = new ObjectOutputStream(
					connection.getOutputStream() );

			// set up input stream for objects
			input = new ObjectInputStream(
					connection.getInputStream() );

			displayArea.append( "\nGot I/O streams\n" );
		}

		// process connection with client
		protected void processConnection() throws IOException
		{
			// send connection successful message to client
			String message = "SERVER>>> Connection successful from : "+connection.getRemoteSocketAddress();
			displayArea.append( "\n" + message );
			output.writeObject("#"+Server4.counter);
			output.flush();
			updateList();
			enterField.setEnabled( true );
		
			
			// process messages sent from client
			while(!connection.isInputShutdown()){
				// read message and display it
				try {

					message = ( String ) input.readObject();
					displayArea.append('\n'+message);
					if (message.equals("LIST")){
						for (int i = 0; i < m.length && m[i]!=null; i++) {
						output.writeObject(m[i].connection.getRemoteSocketAddress().toString()+"//");
						}
					}
					for (int i = 0; i < m.length && m[i]!= null; i++) {
						if (i %2 ==0 ) {m[i+1].output.writeObject('\n'+message ); m[i+1].output.flush(); break; }
						else if (i % 2 != 0) {
						m[i-1].output.writeObject( message ); m[i-1].output.flush(); break;}	
						
					} 
					//displayArea.setCaretPosition(
					//displayArea.getText().length() ); 
				}
				// catch problems reading from client 
				catch ( NullPointerException n ) {
					
				}
				catch ( ClassNotFoundException classNotFoundException ) {
					displayArea.append( "\nUnknown object type received" );
				}
				catch ( IOException ioException ) {
					break;
				} 
			} this.closeConnection();

		}
		// close streams and socket
		protected void closeConnection() 
		{	
			displayArea.append("\n"+connection.getRemoteSocketAddress()+" terminated connection" );
				  
			try { 
				enterField.setText("");
				input.close();  input = null;
				output.close(); output = null;
				connection.close(); connection = null;
				for (int i = 0; i < m.length; i++) {
					if (m[i]==this) m[i]=null;  
				}
				for (int i = 0; i < Server4.m.length; i++) {
					if (Server4.m[i]==this) Server4.m[i]=null;  
				}
			} catch (IOException e) {
				System.out.println("Could not close socket");
			}  
		}
	// send message to client
	public void sendData( String message ) 
	{	
		// send object to client
		try {
			for (int i = 0; i < m.length; i++) {
				if(m[i]!= null && m[i].connection.isConnected()&& m[i].connection!=null ) { m[i].output.writeObject("SERVER>>>"+message); m[i].output.flush();}		
			}
			displayArea.append("\nSERVER>>> "+message);
		}
		// process problems sending object
		catch ( IOException ioException ) {
			displayArea.append( "\nError writing object" );
			//this.closeConnection();
		}
	}	

	public void actionPerformed(ActionEvent arg0) {
		sendData(enterField.getText()); enterField.setText(null);
	}
	}
} // end class Server